<?php
/**
 * Created by PhpStorm.
 * User: lee
 * Date: 2018/9/6
 * Time: 11:03
 */

namespace Biz\module\Classes;

use Biz\cache\activity\OutCoupon as cOutCoupon;
use Biz\cache\Coupon as cCoupon;
use Biz\model\activity\CouponConfig as mCouponConfig;
use Biz\model\activity\CouponRecord as mCouponRecord;
use Biz\model\activity\OutCouponConfig as mOutCouponConfig;
use Biz\model\activity\OutCouponRecord as mOutCouponRecord;
use Biz\module\Classes\Coupon as clsCoupon;
use Doraemon\model\Phone;
use Doraemon\service\Member\PhoneCrypto;
use Doraemon\tools\Log as tLog;

class OutCoupon
{

    public static function getInfoFromDb($id)
    {
        $info = mOutCouponConfig::getInfo($id);


        return $info;
    }

    public static function getInfoByIdMd5FromCache($idMd5)
    {
        $id = cOutCoupon::getIdByIdMd5($idMd5);

        $info = cOutCoupon::getCacheInfo($id);

        mOutCouponConfig::formatInfo($info);

        return $info;
    }

    public static function checkCouponIdListIsBadList($stopTime, $couponIdList = [])
    {
        $stopTime = strtotime($stopTime);

        $couponList = mCouponConfig::getCouponList(['coupon_id' => $couponIdList, 'status' => mCouponConfig::STATUS_CAN_RECEIVE]);

        if (empty($couponList)) {
            return [];
        }

        if (count($couponIdList) != count($couponList)) {
            return [];
        }

        $couponList = array_filter($couponList, function ($v) use ($stopTime) {
            $couponStopTime = strtotime($v['stop_time']);

            if ($couponStopTime < $stopTime && $v['type_time'] == mCouponConfig::TYPE_TIME_STATIC) {
                return true;
            }

            return false;
        });

        return array_column($couponList, 'coupon_id');

    }

    public static function cacheOutCoupon($id)
    {
        if ($id > 0) {
            $info = mOutCouponConfig::getInfo($id, false);

            cOutCoupon::cacheOutCouponConfig($id, $info);

        }

    }

    public static function receive($idMd5, $mobile)
    {
        $result = [];
        $nowTime = time();
        $info = self::getInfoByIdMd5FromCache($idMd5);

        if (empty($info)) {
            throw new \Exception('活动不存在');
        }

        if ($info['status'] != mOutCouponConfig::STATUS_ONLINE) {
            throw new \Exception('来晚一步，活动已过期啦');
        }

        if (strtotime($info['stop_time']) < $nowTime) {

            self::setOffline($info['id']);

            throw new \Exception('来晚啦，活动已过期');
        }

        $record = mOutCouponRecord::getRecordByMobile($info['id'], $mobile);
        $log = mOutCouponRecord::log();
        if (!empty($record)) {
            throw new \Exception('已经领取过此优惠券哦');
        }

//        $mobile = PhoneCrypto::encrypt($mobile, PhoneCrypto::CLIENT_BIZ, PhoneCrypto::VERSIN);
        $user = Phone::getInfoByPhone($mobile);


        if ($info['people_type'] == mOutCouponConfig::PEOPLE_TYPE_NEW_USER) {

            if (!empty($user)) {
                throw new \Exception('你已经是好好住用户了哦');
            }
        }

        $couponIds = array_filter(explode(',', $info['coupon_id_list']));

        $recordData = [
            'title' => $info['title'],
            'outcoupon_id' => $info['id'],
            'mobile' => $mobile
        ];

        $couponList = self::buildWaitSendCoupons($user, $couponIds);

        if (!empty($couponList)) {
            $badList = array_filter($couponList, function ($v) use ($mobile, $couponList) {
                if (empty($v)) {
                    tLog::outcoupon_receive_info("因为通过buildWaitCoupons过滤后产生了脏数据，需要检测出来放到badList列表", ['mobile' => $mobile, 'coupon_list' => $couponList]);

                    return true;
                }
            });

            if (count($couponList) == count($badList)) {
                throw new \Exception('领取失败');
            }

            $couponList = array_filter($couponList, function ($v) {
                if (!empty($v)) {
                    return true;
                }
            });

        }

        if (empty($couponList)) {
            throw new \Exception('领取失败');
        }

        //老用户
        if (!empty($user)) {

            tLog::outcoupon_receive_info("老用户领券成功，得到的信息如下", ['uid' => $user['uid'], 'outcoupon_record_data' => $recordData, 'mobile' => $mobile, 'coupon_list' => $couponList]);


            self::createCoupon($user['uid'], $couponList);

            mOutCouponRecord::createOrEdit(0, array_merge($recordData, ['status' => mOutCouponRecord::STATUS_SUCCESS]));


        } else {

            $outCouponId = mOutCouponRecord::createOrEdit(0, array_merge($recordData, ['status' => mOutCouponRecord::STATUS_WAIT_SEND]));

            cOutCoupon::saveAsyncReceiveCache($idMd5, $mobile, $info['people_type'], json_encode([
                'outcoupon_id' => $outCouponId,
                'coupon_list' => $couponList,
            ], JSON_UNESCAPED_UNICODE));

            tLog::outcoupon_receive_info("站外领券新用户领取", ['mobile' => $mobile, 'out_coupon_id' => $outCouponId, 'outcoupon_record_data' => $recordData, 'coupon_list' => $couponList]);

        }


        return $result;

    }

    public static function createCoupon($uid, $couponList = [])
    {

        if (empty($couponList)) {
            return false;
        }

        foreach ($couponList as $couponInfo) {
            mCouponRecord::insertCoupon($uid, $couponInfo['coupon_id'], $couponInfo);

            tLog::outcoupon_createcoupon_info("站外领券插入新领导的record记录", ['uid' => $uid, 'coupon_id' => $couponInfo['coupon_id'], 'coupon_info' => $couponInfo]);


        }

        return true;
    }

    public static function processAsyncReceive($uid, $mobile)
    {
        $list = cOutCoupon::getAsyncReceive($mobile);

        if (empty($list)) {
            return;
        }


        foreach ($list as $idMd5 => $info) {
            $info = json_decode($info, true);

            self::createCoupon($uid, $info['coupon_list']);

            mOutCouponRecord::upStatusSuccess($info['outcoupon_id']);
        }

        tLog::outcoupon_asyncreceive_info("新用户注册领取优惠券", ['uid' => $uid, 'mobile' => $mobile, 'list' => $list]);

        cOutCoupon::delAsyncReceive($mobile);

    }

    //是否可以将指定优惠券至为不可领
    //return true  可以
    //return int    大于零，即返回所在的正在进行中的活动id   不可以
    public static function checkCouponInOutCouponCantDown($couponId, $supportAssume)
    {
        $onlineList = mOutCouponConfig::getOnlineOutCouponList($supportAssume);

        if (empty($onlineList)) {
            return true;
        }

        $couponIdList = array_map(function ($v) {
            return array_filter(explode(',', $v));
        }, array_column($onlineList, 'coupon_id_list', 'id'));


        if (empty($couponIdList)) {
            return true;
        }

        foreach ($couponIdList as $outCouponId => $couponIds) {
            if (in_array($couponId, $couponIds)) {
                return $outCouponId;
            }
        }


    }

    //优惠券因为可领数为0而变为失效，那么同时优惠券所在的H5站外活动也失效

    public static function setOfflineByCouponId($couponId)
    {
        $onlineList = mOutCouponConfig::getOnlineListByCouponId($couponId);

        if (empty($onlineList)) {
            return;
        }

        array_filter(array_column($onlineList, 'coupon_id_list', 'id'), function ($v, $k) use ($couponId) {
            $couponIds = array_filter(explode(',', $v));

            if (in_array($couponId, $couponIds)) {
                tLog::outcoupon_setofflinebycouponid_info("H5站外领券被coupon的失效而被动下线", ['coupon_id' => $couponId, 'id' => $k]);

                self::setOffline($k);
            }
        }, ARRAY_FILTER_USE_BOTH);
    }


    public static function setOffline($id)
    {
        mOutCouponConfig::setToOffline($id);

        self::cacheOutCoupon($id);

        tLog::outcoupon_setoffline_info("H5站外领券下线", ['id' => $id]);


    }

    public static function buildWaitSendCoupons($user, $couponIds = [])
    {
        $nowTime = time();
        $list = mCouponConfig::select('*', ['coupon_id' => $couponIds]);

        if (empty($list)) {
            return [];
        }

        $list = array_map(function ($v) use ($nowTime, $user) {

            $data = [
                'coupon_id' => $v['coupon_id'],
                'title' => sprintf('满%s减%s', $v['full_amount'], $v['detract_amount']),
                'full_amount' => $v['full_amount'],
                'detract_amount' => $v['detract_amount'],
                'assume' => $v['assume']
            ];

            //相对时间，那么需要在领取时计算优惠券有效期
            if ($v['type_time'] == mCouponConfig::TYPE_TIME_RELATIVELY) {

                $relativeSecond = $v['relative_days'] * 86400;

                $data['start_time'] = date('Y-m-d H:i:s', $nowTime);
                $data['stop_time'] = date('Y-m-d 23:59:59', $nowTime + $relativeSecond);
            } elseif ($v['type_time'] == mCouponConfig::TYPE_TIME_STATIC) {
                $data['start_time'] = $v['start_time'];
                $data['stop_time'] = $v['stop_time'];
            }


            if ($v['shop_id'] > 0) {
                $data['shop_id'] = $v['shop_id'];
            }

            //如果一个用户领取过，则返回空数组
            if (!empty($user)) {
                $hasSum = mCouponRecord::getUserHasCouponSum($user['uid'], $v['coupon_id']);
                if ($hasSum >= $v['receive_rule']) {

                    tLog::outcoupon_buildcoupons_info("老用户因为领取到的优惠券过多而不可再次领取", ['uid' => $user['uid'], 'coupon_id' => $v['coupon_id'], 'has_sum' => $hasSum]);

                    return [];
                }
            }


            $result = cCoupon::incrCouponCount($v['coupon_id']);

            if ($result == -1) {
                clsCoupon::setCouponCannotReceive($v['coupon_id'], [], clsCoupon::REASON_1);

                tLog::outcoupon_buildcoupons_info("优惠券因为领取数不足而不可领取", ['uid' => $user['uid'], 'coupon_id' => $v['coupon_id']]);

                return [];
            } else {

                //发送后优惠券要计数
                mCouponConfig::update(['received_count[+]' => 1], ['coupon_id' => $v['coupon_id']]);

                tLog::outcoupon_buildcoupons_info("用户成功通过站外H5领券领导一张优惠券的权益", ['uid' => $user['uid'], 'coupon_id' => $v['coupon_id']]);

            }


            return $data;
        }, $list);


        return $list;

    }


}